package com.blue.wechat.invoke.spi;

import java.text.MessageFormat;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.blue.http.client.HttpInvoker;
import com.blue.wechat.cache.AccessTokenCache;
import com.blue.wechat.cache.Wechat;
import com.blue.wechat.cache.WechatCache;
import com.blue.wechat.invoke.InvokeException;
import com.blue.wechat.invoke.Invoker;
import com.blue.wechat.invoke.WechatInvokeUtil;
import com.blue.wechat.invoke.WechatInvoker;
import com.blue.wechat.invoke.annotation.WechatUrl;
import com.blue.wechat.invoke.model.AccessToken;

/**
 * 接口授权
 * 
 * @author zhengj
 * @since 1.0 2017年1月25日
 */
@WechatUrl(WechatInvoker.ACCESS_TOKEN)
public class AccessTokenInvoker implements Invoker<AccessToken>
{
	private static Logger logger = LoggerFactory.getLogger(AccessTokenInvoker.class);
	private static final WechatInvoker INVOKER = WechatInvoker.ACCESS_TOKEN;
	public static final int EXPIRE = 900; // 检查过期时间
	
	@Resource
	private HttpInvoker httpInvoker;
	@Resource
	private AccessTokenCache accessTokenCache;
	@Resource
	private WechatCache wechatCache;
	
	public AccessTokenInvoker()
	{
	}

	@Override
	public AccessToken invoke(String code, Object post, String... get) throws InvokeException
	{
		Wechat wechat = wechatCache.getByCode(code);
		if (wechat == null)
			throw InvokeException.getException(InvokeException.WECHAT_NOT_FOUND + code);
		
		AccessToken token = accessTokenCache.getByCode(code);
		int expire = accessTokenCache.expire(code);
		if (token != null && expire > EXPIRE)
			return token;
		
		if (accessTokenCache.lock(code))
		{
			//System.out.println("锁成功");
			token = accessTokenCache.getByCode(code);
			expire = accessTokenCache.expire(code);
			if (token != null && expire > EXPIRE)
				return token;
			try
			{
				return this.invoke(wechat);
			}
			finally
			{
				accessTokenCache.unlock(code);
			}
		}
		else
		{
			//System.out.println("锁失败");
			return this.invoke(wechat);
		}
	}

	private AccessToken invoke(Wechat wechat)
	{
		//System.out.println("获取");
		String url = MessageFormat.format(INVOKER.getUrl(), wechat.getAppId(), wechat.getAppSecret());
		String resp = null;
		long start = System.currentTimeMillis();
		try
		{
			resp = httpInvoker.get(url);
			AccessToken token = WechatInvokeUtil.toResponse(resp, AccessToken.class);
			logger.info("微信[code={}]令牌：{}", wechat.getCode(), token.getAccessToken());
			accessTokenCache.update(wechat.getCode(), token);
			WechatInvokeUtil.log(wechat.getName(), INVOKER.getName(), url, null, null, (int)(System.currentTimeMillis() - start), resp, null);
			return token;
		}
		catch (Exception e)
		{
			WechatInvokeUtil.log(wechat.getName(), INVOKER.getName(), url, null, null, (int)(System.currentTimeMillis() - start), e.getMessage(), e);
			throw InvokeException.getException(InvokeException.WECHAT_ACCESS_TOKEN_ERROR);
		}
	}
}
